#include "constant.h"
#include "../../templates/hstring.h"
#include "../../semantics/visitordata.h"
#include "../../semantics/error.h"
#include "../../code/opcodes.h"

void ConstantCommand::freeData()
{
}
ConstantCommand::~ConstantCommand()
{
}
bool ConstantCommand::negate()
{
	return false;
}
bool IntegralCommand::negate()
{
	m_ll*=-1;
	return true;
}
void IntegralCommand::write(int number,int line,int pos,GraphStream * s)
{
#ifdef _MSC_VER
		fprintf(s->stream,"\tnode_%d [label=\"(%d,%d)\\nINTEGRAL(%I64d)\" shape=\"rectangle\"]\n",number,line,pos,m_ll);
#else
		fprintf(s->stream,"\tnode_%d [label=\"(%d,%d)\\nINTEGRAL(%lld)\" shape=\"rectangle\"]\n",number,line,pos,m_ll);
#endif
}
bool FloatCommand::negate()
{
	m_dbl*=-1;
	return true;
}
void FloatCommand::write(int number,int line,int pos,GraphStream * s)
{
  fprintf(s->stream,"\tnode_%d [label=\"(%d,%d)\\nINTEGRAL(%lf)\" shape=\"rectangle\"]\n",number,line,pos,m_dbl);	
}
void BooleanCommand::write(int number,int line,int pos,GraphStream * s)
{
	const char * boold="FALSE";
	if (m_b) boold="TRUE"; 
	fprintf(s->stream,"\tnode_%d [label=\"(%d,%d)\\nBOOL(%s)\" shape=\"rectangle\"]\n",number,line,pos,boold);
}
/*! Formats a string for output
	\param[in] m_str string
*/
static hst::string  formatString(std::string * m_str)
{
 hst::string tmp=m_str->c_str();
 tmp.replaceAllOccurences("\"","\\\"");
 tmp.replaceAllOccurences("\'","\\\'");
 tmp.replaceAllOccurences("\n","\\\n");
 tmp.replaceAllOccurences("\r","\\\r");
 return tmp;	 
}

void SLiteralsCommand::freeData()
{
	delete m_str;
}
void CharacterCommand::write(int number,int line,int pos,GraphStream * s)
{
 fprintf(s->stream,"\tnode_%d [label=\"(%d,%d)\\nCHAR(%s)\" shape=\"rectangle\"]\n",number,line,pos,formatString(m_str).data());
}
void StringCommand::write(int number,int line,int pos,GraphStream * s)
{
 fprintf(s->stream,"\tnode_%d [label=\"(%d,%d)\\nSTRING(%s)\" shape=\"rectangle\"]\n",number,line,pos,formatString(m_str).data());
}
void  Constant::write(GraphStream * s)
{
	this->accept(s);
	m_behaviour->write(number(),line(),position(),s);
}

AbstractNode * Constant::negate(const YYLTYPE & pos)
{
 if (m_behaviour->negate())
 { 
   setLocation(pos); 
   return this; 
 }
 return this->AbstractNode::negate(pos);
}

Constant::~Constant()
{
  if (isOwningData()) m_behaviour->freeData();
		  delete m_behaviour;
}

std::string Constant::getType(ParentData * data)
{
	return m_behaviour->getType(data);
}

std::string IntegralCommand::getType(ParentData *data)
{
	return "INTEGER";
}
std::string FloatCommand::getType(ParentData *data)
{
	return "REAL";
}
std::string BooleanCommand::getType(ParentData *data)
{
	return "BOOLEAN";
}

std::string CharacterCommand::getType(ParentData * data)
{
	return "CHARACTER";
}

std::string StringCommand::getType(ParentData * data)
{
	return "STRING";
}


bool Constant::checkLogic(ParentData * data)
{
	data->Classes->add(new ExpressionMakesNoSense(this));
	return false;
}

void Constant::fillConstant(ParentData * data)
{
	m_behaviour->fillCTable(data);
}

void Constant::produceCode(ParentData * data)
{
	m_behaviour->produceCode(data);
}
void ConstantCommand::fillCTable(ParentData * data)
{
	
}

void StringCommand::fillCTable(ParentData * data)
{
	m_index=data->currentTable()->createStringLiteral(*(this->m_str));
	m_constructor=data->currentTable()->createStringConstructor();
	m_class=data->currentTable()->createClass("STRING");
}

void FloatCommand::fillCTable(ParentData * data)
{
	m_index=data->currentTable()->createFloat((float)m_dbl);
	m_constructor=data->currentTable()->createRealConstructor();
	m_class=data->currentTable()->createClass("REAL");
}

void IntegralCommand::fillCTable(ParentData * data)
{
	m_index=data->currentTable()->createInteger((int)m_ll);
	m_constructor=data->currentTable()->createIntegerConstructor();
	m_class=data->currentTable()->createClass("INTEGER");
}

void BooleanCommand::fillCTable(ParentData * data)
{
	m_constructor=data->currentTable()->createBooleanConstructor();
	m_class=data->currentTable()->createClass("BOOLEAN");
}

void CharacterCommand::fillCTable(ParentData * data)
{
	m_constructor=data->currentTable()->createCharacterConstructor();
	m_class=data->currentTable()->createClass("CHARACTER");
}

void FloatCommand::produceCode(ParentData * data)
{
	JBFile * curFile=data->currentFile();
	curFile->write(JVMNEW);
	curFile->write(m_class);
	curFile->write(DUP);
	curFile->write(LDC);
	curFile->write((unsigned char)m_index);
	curFile->write(INVOKESPECIAL);
	curFile->write(m_constructor);
}

void StringCommand::produceCode(ParentData * data)
{
	JBFile * curFile=data->currentFile();
	curFile->write(JVMNEW);
	curFile->write(m_class);
	curFile->write(DUP);
	curFile->write(LDC);
	curFile->write((unsigned char)m_index);
	curFile->write(INVOKESPECIAL);
	curFile->write(m_constructor);
}

void IntegralCommand::produceCode(ParentData * data)
{
	JBFile * curFile=data->currentFile();
	curFile->write(JVMNEW);
	curFile->write(m_class);
	curFile->write(DUP);
	curFile->write(LDC);
	curFile->write((unsigned char)m_index);
	curFile->write(INVOKESPECIAL);
	curFile->write(m_constructor);
}

void BooleanCommand::produceCode(ParentData * data)
{
	JBFile * curFile=data->currentFile();
	curFile->write(JVMNEW);
	curFile->write(m_class);
	curFile->write(DUP);
	if (m_b)
	{
		curFile->write(ICONST_1);
	}
	else
	{
		curFile->write(ICONST_0);
	}
	curFile->write(INVOKESPECIAL);
	curFile->write(m_constructor);
}

void CharacterCommand::produceCode(ParentData * data)
{
	JBFile * curFile=data->currentFile();
	curFile->write(JVMNEW);
	curFile->write(m_class);
	curFile->write(DUP);
	curFile->write(BIPUSH);
	curFile->write((*m_str)[0]);
	curFile->write(INVOKESPECIAL);
	curFile->write(m_constructor);
}